package net.fkzg.framework.application.data;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import net.fkzg.framework.util.EnvUtil;
import org.smartboot.http.common.utils.StringUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import static net.fkzg.framework.util.Constant.DELIMITER;
import static net.fkzg.framework.util.Constant.PROJECT_NAME;

@Slf4j
public class StorageDataHelper {

    private static JedisPool pool;

    public synchronized static void init() {
        if (null != pool) {
            log.warn("the redis pool should only init once!");
            return;
        }
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(128);
        config.setMaxIdle(8);
        config.setTestOnBorrow(true);
        String host = EnvUtil.getPropValue("redis.host");
        int port = Integer.parseInt(EnvUtil.getPropValue("redis.port"));
        String password = EnvUtil.getPropValue("redis.password");
        if (StringUtils.isEmpty(password)) {
            password = null;
        }
        int database = Integer.parseInt(EnvUtil.getPropValue("redis.database"));
        pool = new JedisPool(config, host, port, 1000, password, database);
    }

    public static String getVal(String keyPrefix, String key) {
        Jedis jedis = pool.getResource();
        return jedis.get(PROJECT_NAME + DELIMITER + keyPrefix + DELIMITER + key);
    }

    public static void setVal(String keyPrefix, String key, String val) {
        Jedis jedis = pool.getResource();
        jedis.setnx(PROJECT_NAME + DELIMITER + keyPrefix + DELIMITER + key, val);
    }

    private static <T> String getDataKeyPrefix(Class<T> tClass) {
        StoragePrefix keyPrefix = tClass.getAnnotation(StoragePrefix.class);
        if (null == keyPrefix || StringUtils.isBlank(keyPrefix.value())) {
            throw new IllegalArgumentException("the class must have annotation KeyPrefix anc config value");
        }
        return PROJECT_NAME + DELIMITER + keyPrefix.value() + DELIMITER;
    }

    public static <T> void saveData(String id, Object data) {
        Jedis jedis = pool.getResource();
        jedis.set(getDataKeyPrefix(data.getClass()) + id, JSON.toJSONString(data));
    }

    public static <T> boolean notExistData(String id, Class<T> tClass) {
        Jedis jedis = pool.getResource();
        return !jedis.exists(getDataKeyPrefix(tClass) + id);
    }

    public static <T> Optional<T> getDataById(String id, Class<T> tClass) {
        Jedis jedis = pool.getResource();
        String k = getDataKeyPrefix(tClass) + id;
        return Optional.of(jedis.get(k)).map(v -> JSONObject.parseObject(jedis.get(k), tClass));
    }

    public static <T> Map<String, T> getDataMap(Class<T> tClass) {
        Map<String, T> map = new HashMap<>();
        Jedis jedis = pool.getResource();
        Set<String> keys = jedis.keys(getDataKeyPrefix(tClass) + "*");
        for (String key : keys) {
            Optional.of(jedis.get(key)).ifPresent(v -> {
                map.put(key, JSONObject.parseObject(v, tClass));
            });
        }
        return map;
    }

}
